/**********************************************************************\

 Copyright 2012 Diggory Blake

 This file is part of klip-engine

 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.

\**********************************************************************/
#pragma once

#include <stdint.h>

#pragma comment(lib, "libpng15.lib")
#pragma comment(lib, "jpeg.lib")
#pragma comment(lib, "turbojpeg.lib")
#pragma comment(lib, "zlib.lib")

struct kDataView;

class kImageFile;
class kResources;
class kStream;

#include "kmath.h"
#include "keimageformat.h"
#include "kbase.h"

struct kImageHeader {
	keImageFormat format;
	uint32_t width;
	uint32_t height;
	uint32_t depth;		// 3 OR 4 = RGB OR RGBA
};

class kImageFile : public kBase {
	template<typename T> friend class kImageFileBase;

private:
	static std::map<keImageFormat, kImageFile*>& _fileTypes();

protected:
	virtual bool tryLoad(kStream* source, kImageHeader* header, std::function<void (uint32_t, const uint8_t*)> lambda) = 0;
	virtual bool trySave(kStream* dest, const kImageHeader* header, std::function<void (uint32_t, uint8_t*)> lambda) = 0;

public:
	static bool load(kStream* source, kImageHeader* header, std::function<void (uint32_t, const uint8_t*)> lambda);
	static bool save(kStream* dest, const kImageHeader* header, std::function<void (uint32_t, uint8_t*)> lambda);
};

template<typename T> class kImageFileBase : public kImageFile {
protected:
	static T _instance;

	kImageFileBase() { };

	void supports(keImageFormat format) {
		_fileTypes().insert(std::make_pair(format, (kImageFile*)this));
	}
};
template<typename T> T kImageFileBase<T>::_instance;

class kImageFilePNG : public kImageFileBase<kImageFilePNG> {
	friend class kImageFileBase<kImageFilePNG>;

private:
	inline kImageFilePNG() { supports(keImage_PNG); }

protected:
	virtual bool tryLoad(kStream* source, kImageHeader* header, std::function<void (uint32_t, const uint8_t*)> lambda);
	virtual bool trySave(kStream* dest, const kImageHeader* header, std::function<void (uint32_t, uint8_t*)> lambda);
};
class kImageFileJPG : public kImageFileBase<kImageFileJPG> {
	friend class kImageFileBase<kImageFileJPG>;

private:
	inline kImageFileJPG() { supports(keImage_JPG); }

protected:
	virtual bool tryLoad(kStream* source, kImageHeader* header, std::function<void (uint32_t, const uint8_t*)> lambda);
	virtual bool trySave(kStream* dest, const kImageHeader* header, std::function<void (uint32_t, uint8_t*)> lambda);
};
